﻿using System;
using Core.Combat.CoreModule;
using Core.Combat.FlyerObj.Data;
using GCFramework.Utility.ObjectPool;
using Sirenix.OdinInspector;
using UnityEngine;
using UnityEngine.Serialization;

namespace Core.Combat.FlyerObj
{
    public class Bullet : Poolable
    {
        public struct BulletDataPipeline
        {
            public int splitCount;
        }
        
        [ShowInInspector,ReadOnly]
        public BulletData BulletData { get; protected set; }
        public BulletFireCoreModule BulletFireCoreModule { get; private set; }
        public BulletBehaviourCoreModule BulletBehaviourCoreModule { get; private set; }
        public BulletEffectCoreModule BulletEffectCoreModule { get; private set; }

        #region Components

        private CircleCollider2D _cc2D;
        public BulletGenerator Generator { get; private set; }
        public AttackObject AttackObject { get; private set; }

        #endregion
        
        #region Property Variables

        public bool IsInitialized { get; protected set; }
        public Vector2 FlyDirection => BulletBehaviourCoreModule.flyDirection;

        #endregion

        #region Hide Variables

        private float _rayDistance;
        private float _liveTimer;
        
        #endregion

        #region Inspector Editor

        [Title("碰撞检测优化")]
        public float triggerDistScale = 2;
        public float hitCheckInterval = 0.1f;
        
        #endregion

        #region Bullet Main Methods

        private void Awake()
        {
            _cc2D = GetComponent<CircleCollider2D>();
            AttackObject = GetComponent<AttackObject>();
            
            BulletFireCoreModule = new BulletFireCoreModule(this);
            BulletBehaviourCoreModule = new BulletBehaviourCoreModule(this);
            BulletEffectCoreModule = new BulletEffectCoreModule(this);
        }

        private void Start()
        {
            _hitCheckRadius = _cc2D.radius * triggerDistScale;
        }

        private void Update()
        {
            if (!IsInitialized)
                return;
            
            BulletFireCoreModule.Update();
            BulletBehaviourCoreModule.Update();
            BulletEffectCoreModule.Update();
            
            UpdateTimer();
        }

        private void FixedUpdate()
        {
            if (!IsInitialized)
                return;
            
            BulletFireCoreModule.FixedUpdate();
            BulletBehaviourCoreModule.FixedUpdate();
            BulletEffectCoreModule.FixedUpdate();
            
            TriggerCheck();
        }

        protected override void OnDisable()
        {
            base.OnDisable();
            IsInitialized = false;
        }

        private void OnDestroy()
        {
            IsInitialized = false;
            BulletFireCoreModule.Destroy();
            BulletBehaviourCoreModule.Destroy();
            BulletEffectCoreModule.Destroy();
        }

        #endregion

        public bool CanHit(Collider2D hitObj)
        {
            return AttackObject.hitProperties.hitLayer.IsInLayer(hitObj.gameObject.layer)
                   || AttackObject.hitProperties.hitTags.IsInTags(hitObj.tag);
        }
        
        public void SetGenerator(BulletGenerator generator)
        {
            Generator = generator;
        }
        
        public void InitBullet(Vector3 pos, Vector3 dir, BulletData data)
        {
            gameObject.SetActive(true);
            BulletData ??= new BulletData();
            BulletData.InitData(data);
            BulletFireCoreModule.SetFireInfo(pos, dir);
            
            BulletFireCoreModule.InitState();
            BulletBehaviourCoreModule.InitState();
            BulletEffectCoreModule.InitState();
            IsInitialized = true;
            _isTriggerEnter = false;

            _liveTimer = BulletData.bulletLiveTime;
            _lastFramePos = transform.position;
        }

        private void OnTriggerEnter2D(Collider2D other)
        {
            if (_isTriggerEnter)
                return;
            
            if (other && !other.CompareTag("Player"))
            {
                OnBulletHitHandle(other);
            }
        }

        private void OnTriggerExit2D(Collider2D other)
        {
            if (_isTriggerEnter)
            {
                _isTriggerEnter = false;
            }
        }

        /// <summary>
        /// 当子弹隐藏对象时进行隐藏处理的逻辑
        /// </summary>
        public void Stop()
        {
            gameObject.SetActive(false);
            BulletFireCoreModule.OnBulletStop();
            BulletBehaviourCoreModule.OnBulletStop();
            BulletEffectCoreModule.OnBulletStop();
        }

        private void UpdateTimer()
        {
            if (_liveTimer > 0)
            {
                _liveTimer -= Time.deltaTime;
                if (_liveTimer <= 0)
                {
                    Stop();
                }
            }
        }

        public void BulletDataOverride(BulletDataPipeline dataPipeline)
        {
            BulletFireCoreModule.OnBulletDataOverride(dataPipeline);
            BulletBehaviourCoreModule.OnBulletDataOverride(dataPipeline);
            BulletEffectCoreModule.OnBulletDataOverride(dataPipeline);
        }

        /// <summary>
        /// 子弹击中处理
        /// </summary>
        /// <param name="hitObj"></param>
        private void OnBulletHitHandle(Collider2D hitObj)
        {
            BulletBehaviourCoreModule.OnBulletHit(hitObj);
            BulletEffectCoreModule.OnBulletHit(hitObj);
        }
        
        #region 碰撞检测优化

        private bool _isTriggerEnter;
        private float _hitCheckRadius;
        private float _lastHitCheckTime;
        private Vector2 _lastFramePos;
        [HideInInspector] public RaycastHit2D hitCheckResult;
        /// <summary>
        /// 是否开启击中碰撞检测优化
        /// </summary>
        public bool OpenHitCheckOpt => BulletData.flyingSpeed > 100;
        private void TriggerCheck()
        {
            if (_isTriggerEnter || !OpenHitCheckOpt)
                return;
            
            if (Time.time < _lastHitCheckTime + hitCheckInterval)
                return;

            // 计算这一帧移动的距离，用于射线检测路径上是否击中物体
            _rayDistance = Vector2.Distance(transform.position, _lastFramePos) + _hitCheckRadius * 2f;
            
            hitCheckResult = Physics2D.Raycast(_lastFramePos + -FlyDirection.normalized * _hitCheckRadius, FlyDirection * _rayDistance);
            if (hitCheckResult.collider && !hitCheckResult.collider.CompareTag("Player"))
            {
                Debug.Log($"检测到目标{hitCheckResult.collider.name}");
                OnBulletHitHandle(hitCheckResult.collider);
                transform.position = hitCheckResult.point;
                _isTriggerEnter = true;
            }

            _lastHitCheckTime = Time.time;
            _lastFramePos = transform.position; // 记录这一帧位置留给下一帧使用
        }

        #endregion

#if UNITY_EDITOR
        private void OnDrawGizmosSelected()
        {
            if (!IsInitialized)
                return;
            
            Gizmos.color = Color.green;
            Gizmos.DrawRay(_lastFramePos, BulletBehaviourCoreModule.flyDirection * _rayDistance);
            
            Gizmos.color = Color.yellow;
            Gizmos.DrawWireSphere(transform.position, BulletData.behaviourCoreData.traceRange);
        }
#endif
    }
}